package com.controller;

import com.BaseWebSocketTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Disabled;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import static org.junit.jupiter.api.Assertions.*;

/**
 * WebSocket性能测试
 * 注意：这些测试可能会影响系统性能，建议在测试环境中运行
 */
@Disabled("性能测试，需要手动启用")
public class WebSocketPerformanceTest extends BaseWebSocketTest {

    private static final int THREAD_COUNT = 10;
    private static final int MESSAGE_COUNT = 100;
    private static final int TIMEOUT_SECONDS = 30;

    @Test
    void testConcurrentMessageSending() throws InterruptedException {
        // 测试并发消息发送性能
        ExecutorService executor = Executors.newFixedThreadPool(THREAD_COUNT);
        CountDownLatch latch = new CountDownLatch(THREAD_COUNT);
        AtomicInteger successCount = new AtomicInteger(0);
        AtomicInteger failureCount = new AtomicInteger(0);
        AtomicLong totalTime = new AtomicLong(0);

        long startTime = System.currentTimeMillis();

        for (int i = 0; i < THREAD_COUNT; i++) {
            final int threadId = i;
            executor.submit(() -> {
                try {
                    for (int j = 0; j < MESSAGE_COUNT; j++) {
                        long messageStartTime = System.currentTimeMillis();
                        
                        boolean success = sendMessageToUser("user" + threadId, "Message " + j);
                        
                        long messageEndTime = System.currentTimeMillis();
                        totalTime.addAndGet(messageEndTime - messageStartTime);
                        
                        if (success) {
                            successCount.incrementAndGet();
                        } else {
                            failureCount.incrementAndGet();
                        }
                        
                        // 避免发送过快
                        Thread.sleep(10);
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                } finally {
                    latch.countDown();
                }
            });
        }

        // 等待所有线程完成
        assertTrue(latch.await(TIMEOUT_SECONDS, TimeUnit.SECONDS), "并发测试超时");

        long endTime = System.currentTimeMillis();
        long totalTestTime = endTime - startTime;

        // 打印性能统计
        System.out.println("=== 并发消息发送性能测试结果 ===");
        System.out.println("线程数: " + THREAD_COUNT);
        System.out.println("每线程消息数: " + MESSAGE_COUNT);
        System.out.println("总消息数: " + (THREAD_COUNT * MESSAGE_COUNT));
        System.out.println("成功消息数: " + successCount.get());
        System.out.println("失败消息数: " + failureCount.get());
        System.out.println("总测试时间: " + totalTestTime + "ms");
        System.out.println("平均消息发送时间: " + (totalTime.get() / (THREAD_COUNT * MESSAGE_COUNT)) + "ms");
        System.out.println("消息发送速率: " + ((THREAD_COUNT * MESSAGE_COUNT) * 1000.0 / totalTestTime) + " 消息/秒");

        // 验证性能指标
        assertTrue(successCount.get() > 0, "应该有成功的消息发送");
        assertTrue(totalTestTime < TIMEOUT_SECONDS * 1000, "测试时间不应超过超时时间");

        executor.shutdown();
    }

    @Test
    void testMemoryUsage() throws InterruptedException {
        // 测试内存使用情况
        Runtime runtime = Runtime.getRuntime();
        
        // 强制垃圾回收
        System.gc();
        long initialMemory = runtime.totalMemory() - runtime.freeMemory();
        
        System.out.println("=== 内存使用测试 ===");
        System.out.println("初始内存使用: " + (initialMemory / 1024 / 1024) + "MB");
        
        // 创建大量消息
        int messageCount = 1000;
        for (int i = 0; i < messageCount; i++) {
            sendMessageToUser("memoryuser", "Memory test message " + i);
            
            if (i % 100 == 0) {
                long currentMemory = runtime.totalMemory() - runtime.freeMemory();
                System.out.println("消息 " + i + " 后内存使用: " + (currentMemory / 1024 / 1024) + "MB");
            }
        }
        
        // 强制垃圾回收
        System.gc();
        long finalMemory = runtime.totalMemory() - runtime.freeMemory();
        
        System.out.println("最终内存使用: " + (finalMemory / 1024 / 1024) + "MB");
        System.out.println("内存增长: " + ((finalMemory - initialMemory) / 1024 / 1024) + "MB");
        
        // 验证内存使用合理
        long memoryGrowth = finalMemory - initialMemory;
        assertTrue(memoryGrowth < 100 * 1024 * 1024, "内存增长不应超过100MB");
    }

    @Test
    void testConnectionStress() throws InterruptedException {
        // 测试连接压力
        ExecutorService executor = Executors.newFixedThreadPool(50);
        CountDownLatch latch = new CountDownLatch(50);
        AtomicInteger connectionCount = new AtomicInteger(0);

        long startTime = System.currentTimeMillis();

        for (int i = 0; i < 50; i++) {
            final int connectionId = i;
            executor.submit(() -> {
                try {
                    // 模拟连接建立
                    connectionCount.incrementAndGet();
                    
                    // 模拟连接保持一段时间
                    Thread.sleep(1000);
                    
                    // 模拟连接关闭
                    connectionCount.decrementAndGet();
                    
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                } finally {
                    latch.countDown();
                }
            });
        }

        // 等待所有连接完成
        assertTrue(latch.await(TIMEOUT_SECONDS, TimeUnit.SECONDS), "连接压力测试超时");

        long endTime = System.currentTimeMillis();
        long totalTime = endTime - startTime;

        System.out.println("=== 连接压力测试结果 ===");
        System.out.println("连接数: 50");
        System.out.println("总测试时间: " + totalTime + "ms");
        System.out.println("平均连接时间: " + (totalTime / 50) + "ms");

        // 验证连接处理正常
        assertEquals(0, connectionCount.get(), "所有连接应该已关闭");

        executor.shutdown();
    }

    @Test
    void testMessageThroughput() throws InterruptedException {
        // 测试消息吞吐量
        int messageCount = 1000;
        long startTime = System.currentTimeMillis();
        
        for (int i = 0; i < messageCount; i++) {
            sendMessageToUser("throughputuser", "Throughput test message " + i);
        }
        
        long endTime = System.currentTimeMillis();
        long totalTime = endTime - startTime;
        
        double throughput = messageCount * 1000.0 / totalTime;
        
        System.out.println("=== 消息吞吐量测试结果 ===");
        System.out.println("消息数量: " + messageCount);
        System.out.println("总时间: " + totalTime + "ms");
        System.out.println("吞吐量: " + throughput + " 消息/秒");
        
        // 验证吞吐量
        assertTrue(throughput > 0, "吞吐量应该大于0");
        assertTrue(totalTime < TIMEOUT_SECONDS * 1000, "测试时间不应超过超时时间");
    }

    @Test
    void testLongRunningConnection() throws InterruptedException {
        // 测试长连接稳定性
        int connectionDuration = 10; // 10秒
        long startTime = System.currentTimeMillis();
        
        System.out.println("=== 长连接稳定性测试 ===");
        System.out.println("连接持续时间: " + connectionDuration + "秒");
        
        // 模拟长连接
        for (int i = 0; i < connectionDuration; i++) {
            sendMessageToUser("longrunninguser", "Long running message " + i);
            Thread.sleep(1000);
            
            if (i % 2 == 0) {
                System.out.println("连接运行 " + (i + 1) + " 秒");
            }
        }
        
        long endTime = System.currentTimeMillis();
        long totalTime = endTime - startTime;
        
        System.out.println("长连接测试完成，总时间: " + totalTime + "ms");
        
        // 验证长连接稳定性
        assertTrue(totalTime >= connectionDuration * 1000, "连接时间应该至少达到预期时间");
    }

    @Test
    void testConcurrentUserConnections() throws InterruptedException {
        // 测试并发用户连接
        int userCount = 20;
        ExecutorService executor = Executors.newFixedThreadPool(userCount);
        CountDownLatch latch = new CountDownLatch(userCount);
        AtomicInteger activeUsers = new AtomicInteger(0);

        long startTime = System.currentTimeMillis();

        for (int i = 0; i < userCount; i++) {
            final int userId = i;
            executor.submit(() -> {
                try {
                    activeUsers.incrementAndGet();
                    
                    // 模拟用户活动
                    for (int j = 0; j < 10; j++) {
                        sendMessageToUser("concurrentuser" + userId, "Concurrent message " + j);
                        Thread.sleep(100);
                    }
                    
                    activeUsers.decrementAndGet();
                    
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                } finally {
                    latch.countDown();
                }
            });
        }

        // 等待所有用户完成
        assertTrue(latch.await(TIMEOUT_SECONDS, TimeUnit.SECONDS), "并发用户测试超时");

        long endTime = System.currentTimeMillis();
        long totalTime = endTime - startTime;

        System.out.println("=== 并发用户连接测试结果 ===");
        System.out.println("用户数: " + userCount);
        System.out.println("总测试时间: " + totalTime + "ms");
        System.out.println("平均每用户时间: " + (totalTime / userCount) + "ms");

        // 验证并发处理正常
        assertEquals(0, activeUsers.get(), "所有用户应该已完成活动");

        executor.shutdown();
    }
}
